package com.panopset.gui;

import static com.panopset.Util.centerInScreen;
import static com.panopset.Util.getIntegerFromProperty;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.net.URL;
import java.util.Properties;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenuBar;

import com.panopset.ApplicationInterface;
import com.panopset.centralen.resource.Accessor;

/**
 * Frame that remembers where it was last closed, and its dimensions.
 * Favicon can also be set.
 *
 * @author Karl Dinwiddie
 *
 */
public class FlexFrame {

    private ApplicationInterface applicationInterface;
    // Frame attribute keys.
    public final String W = "W";
    public final String H = "H";
    public final String X = "X";
    public final String Y = "Y";
    private JFrame customFrame;
    private JFrame frame;
    private Dimension defaultSize;

    public void setVisible(boolean value) {
        if (value == true && applicationInterface != null) {
                Properties properties = applicationInterface.getProperties();
                Integer w = null;
                Integer h = null;
                Integer x = null;
                Integer y = null;
                if (properties != null) {
                    w = getIntegerFromProperty(properties, W);
                    h = getIntegerFromProperty(properties, H);
                    x = getIntegerFromProperty(properties, X);
                    y = getIntegerFromProperty(properties, Y);
                }
                Dimension size = null;
                Point location = null;
                if (w != null && h != null && x != null && y != null) {
                    size = new Dimension(w, h);
                    location = new Point(x, y);
                } else {
                    size = getDefaultSize();
                    location = centerInScreen(size);
                }
                getFrame().setSize(size);
                getFrame().setLocation(location);
        }
        getFrame().setVisible(value);
    }

    public void quit() {
        if (applicationInterface != null) {
            Properties properties = applicationInterface.getProperties();
            if (properties != null) {
                properties.put(W, "" + getFrame().getSize().width);
                properties.put(H, "" + getFrame().getSize().height);
                properties.put(X, "" + getFrame().getLocation().x);
                properties.put(Y, "" + getFrame().getLocation().y);
            }
            applicationInterface.quit();
        }
        getFrame().dispose();
    }

    public JFrame getFrame() {
        if (frame == null) {
            frame = customFrame == null ? new JFrame() : customFrame;
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.addWindowListener(new WindowListener() {

                public void windowClosing(WindowEvent e) {
                    quit();
                }

                public void windowActivated(WindowEvent e) {
                }

                public void windowClosed(WindowEvent e) {
                }

                public void windowDeactivated(WindowEvent e) {
                }

                public void windowDeiconified(WindowEvent e) {
                }

                public void windowIconified(WindowEvent e) {
                }

                public void windowOpened(WindowEvent e) {
                }
            });
        }
        return frame;
    }

    private void setMenuBar(JMenuBar menuBar) {
        getFrame().setJMenuBar(menuBar);
    }

    private FlexFrame() {
        // prevent instantiation outside of Builder.
    }

    public Dimension getDefaultSize() {
        if (defaultSize == null) {
            defaultSize = new Dimension(600, 500);
        }
        return defaultSize;
    }

    public static class Builder {

        private ApplicationInterface applicationInterface;
        private Dimension defaultSize;
        private ImageIcon frameIcon;
        private JMenuBar menuBar;
        private String title;
        private JFrame customFrame;

        public FlexFrame construct() {
            FlexFrame ff = new FlexFrame();
            if (customFrame != null) {
                ff.customFrame = customFrame;
            }
            ff.defaultSize = defaultSize;
            if (frameIcon != null) {
                ff.getFrame().setIconImage(frameIcon.getImage());
            }
            if (menuBar != null) {
                ff.setMenuBar(menuBar);
            }
            if (title != null) {
                ff.getFrame().setTitle(title);
            }
            ff.applicationInterface = applicationInterface;
            return ff;
        }

        /**
         * Provide your own JFrame.
         * @param customFrame
         * @return Builder
         */
        public Builder customFrame(JFrame customFrame) {
            this.customFrame = customFrame;
            return this;
        }

        /**
         * Optional, default is 600,500.
         * @param defaultSize Size of frame;
         * @return Builder.
         */
        public Builder defaultSize(Dimension defaultSize) {
            this.defaultSize = defaultSize;
            return this;
        }

        /**
         * 16x16 icon image from package resource.
         * @param path Path to image, ie &quot;com/company/icon.png&quot;.
         * @return Builder.
         */
        public Builder packageIcon(String path) {
            if (path == null) {
                return this;
            }
            return urlIcon(Accessor.getPackageURL(path));
        }

        /**
         * URL must point to a 16x16 icon.
         * @param iconURL
         * @return Builder.
         */
        public Builder urlIcon(URL iconURL) {
            if (iconURL == null) {
                return this;
            }
            return frameIcon(new ImageIcon(iconURL));
        }

        /**
         * frameIcon must be size 16x16.
         * @param frameIcon
         * @return Builder
         */
        public Builder frameIcon(ImageIcon frameIcon) {
            this.frameIcon = frameIcon;
            return this;
        }

        /**
         *
         * @param flexMenuBar
         * @return Builder
         */
        public Builder menuBar(JMenuBar menuBar) {
            this.menuBar = menuBar;
            return this;
        }

        public Builder title(String title) {
            this.title = title;
            return this;
        }

        public Builder applicationInterface(ApplicationInterface applicationInterface) {
            this.applicationInterface = applicationInterface;
            return this;
        }
    }
}
